﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using EbbinghausWord.Common;
using EbbinghausWord.DAL;
using EbbinghausWord.Entities;

namespace EbbinghausWord.BLL
{
    /// <summary>
    /// 单词学习管理
    /// </summary>
    public static class WordBookManager
    {
        #region private field
        private static List<WordEntity> _wordbook = null;
        //private static Queue<WordEntity> _queue = new Queue<WordEntity>();


        #endregion

        #region public method

        /// <summary>
        /// 初始化单词本
        /// </summary>
        public static void InitUserWord()
        {
            _wordbook = new UserDataDAL().GetAllUserBook();
        }

        /// <summary>
        /// 获得下一个单词
        /// </summary>
        /// <returns></returns>
        public static WordEntity GetNextWord()
        {
            var et = new ExecuteTimer(false);

            //当前队列是否小于指定数值
            if (WordQueueManager.Count < SystemConfig.MinQueueWordCount)
            {
                //是否有需要复习的熟词
                //var completedWordList = GetCompletedWordToReviewWithoutQueue();
                //et.Show("GetCompletedWordToReviewWithoutQueue");

                //if (completedWordList.Count > 0)
                //{
                //    //将指定数量的熟词加入到队列中
                //    completedWordList.AddToQueue(SystemConfig.IncreaseQueueWordCount);
                //    et.Show("completedWordList");
                //}
                //else 

                //单词本中是否有当前需要记忆的单词
                if (IsHaveWordInWordBook())
                {
                    et.Show("IsHaveWordInWordBook");
                    //将单词本中需要复习的单词 加入到队列中
                    GetReviewWordBookWithoutQueue().AddToQueue(SystemConfig.IncreaseQueueWordCount);
                    et.Show("GetReviewWordBookWithoutQueue");
                }
                //加载新的单词
                else
                {
                    et.Show("IsHaveWordInWordBook");
                    //从字典中加载x个新单词（不在用户词典、不在队列中），不足x加载最大数量
                    var newWords = _wordbook.Where(x => !x.IsInTheWordBook)
                        .GroupJoin(WordQueueManager.Queue, x => x.English, x => x.English,
                        (x, y) => new { Word = x, Count = y.Count() }).Where(x => x.Count == 0);
                    var resultWords = (new UserConfig().OrderType == 0
                        ? newWords : newWords.OrderBy(x => x.Word.OrderRandom))
                        .Take(SystemConfig.IncreaseQueueWordCount)
                        .Select(x => x.Word)
                        .ToList();
                    et.Show("QueryNewWord");

                    resultWords.AddToQueue(SystemConfig.IncreaseQueueWordCount);

                    //WordBook.Where(x => !x.IsInTheWordBook && !WordQueueManager.Contains(x))
                    //                   .ToList().AddToQueue(SystemConfig.IncreaseQueueWordCount);
                    et.Show("从字典中加载x个新单词");
                }
            }

            //队列中是否还有单词
            return WordQueueManager.Peek();
        }

        /// <summary>
        /// 清除用户学习记录
        /// </summary>
        public static void ClearWorkbook()
        {
            var et = new ExecuteTimer(false);

            UserDataDAL.ClearDb();
            et.Show("ClearDB");

            //StoreManager.CopyDBFile("User.sdf", true);
            //UserDataDAL.Open();

            //DBTest.CreateUserDB();
            //et.Show("CreateUserDB");

            //清除队列
            //_queue.Clear();
            WordQueueManager.InitQueue();

            //初始化用户单词本
            InitUserWord();
            IsNeedReflesh = true;
        }

        /// <summary>
        /// 记住单词
        /// </summary>
        public static WordEntity RememberWord()
        {
            var et = new ExecuteTimer(false);

            //当前单词出队
            var wordEntity = WordQueueManager.Dequeue();

            //当前单词是否在单词本中
            if (wordEntity.IsInTheWordBook)
            {
                //修改单词的记忆级别
                ReviewManager.SetWordRemeberLevel(wordEntity);
            }
            else
            {
                //是否第3次记住
                if (++wordEntity.RememberTimes < SystemConfig.NewWordRemeberTimes)
                {
                    WordQueueManager.Enqueue(wordEntity, wordEntity.RememberTimes + 2);
                }
                else
                {
                    //加入到单词本
                    ReviewManager.AddToWordbook(wordEntity);
                }
            }

            //当前单词 “记住” 计数器 加1
            wordEntity.RememberCounter++;

            //修改单词最后学习时间
            wordEntity.LastRemeberingDateTime = DateTime.Now;
            et.Show("other");

            Edit(wordEntity);
            et.Show("AsynEdit");

            var nextWord = GetNextWord();
            et.Show("GetNextWord");
            return nextWord;
        }

        /// <summary>
        /// 没记住单词
        /// </summary>
        /// <returns></returns>
        public static WordEntity ForgetWord()
        {
            var et = new ExecuteTimer(false);

            //当前单词出队
            var wordEntity = WordQueueManager.Dequeue();
            //设置记忆次数为0
            wordEntity.RememberTimes = 0;
            //设置记忆等级为0
            wordEntity.RememberLevel = 0;
            //从单词本移除
            wordEntity.IsInTheWordBook = false;
            wordEntity.NotRememberCounter++;
            //当前单词重新入队，排队队列的第2位
            WordQueueManager.Enqueue(wordEntity, 2);
            et.Show("before");
            //保存
            Edit(wordEntity);
            et.Show("EditOrCreate");

            return GetNextWord();
        }

        /// <summary>
        /// 彻底记住当前单词
        /// </summary>
        public static WordEntity CompleteRemeberWord()
        {
            //当前单词出队
            var wordEntity = WordQueueManager.Dequeue();

            //加入到单词本
            if (!wordEntity.IsInTheWordBook)
            {
                wordEntity.IsInTheWordBook = true;
                wordEntity.StartRemeberingDateTime = DateTime.Now;
            }

            //设置记忆等级为9，彻底记住
            wordEntity.RememberLevel = SystemConfig.AchievementRememberLevel;

            //当前单词 “记住” 计数器 加1
            wordEntity.RememberCounter++;

            //修改单词最后学习时间
            wordEntity.LastRemeberingDateTime = DateTime.Now;

            //保存数据
            Edit(wordEntity);

            return GetNextWord();
        }

        /// <summary>
        /// 获得所有记住的单词
        /// </summary>
        /// <returns></returns>
        public static List<WordEntity> GetAchievementWords()
        {
            return _wordbook.Where(x => x.RememberLevel == SystemConfig.AchievementRememberLevel).ToList();
        }

        /// <summary>
        /// 获得学习中的单词列表，其中不包括 不在单词本 和 已经记住的单词
        /// </summary>
        /// <returns></returns>
        public static List<WordEntity> GetLearningWords()
        {
            return _wordbook.Where(x => x.IsInTheWordBook
                && x.RememberLevel != SystemConfig.AchievementRememberLevel)
                .OrderByDescending(x => x.RememberLevel).ToList();
        }

        /// <summary>
        /// 获得单词本中单词，包括学习中 和 已经记住的单词
        /// </summary>
        /// <returns></returns>
        public static List<WordEntity> GetWordsInWordbook()
        {
            return _wordbook.Where(x => x.IsInTheWordBook).ToList();
        }

        /// <summary>
        /// 根据英文获得单词实体
        /// </summary>
        /// <param name="english"></param>
        /// <returns></returns>
        public static WordEntity GetWordByEnglish(string english)
        {
            return _wordbook.First(x => x.English == english);
        }

        /// <summary>
        /// 顺序排列单词本
        /// </summary>
        public static void OrderWordBook()
        {
            _wordbook = _wordbook.OrderBy(x => x.English).ToList();
        }

        /// <summary>
        /// 乱序排列单词本
        /// </summary>
        public static void UnorderWordBook()
        {
            _wordbook = _wordbook.OrderBy(x => x.OrderRandom).ToList();
        }

        /// <summary>
        /// 获得当前的书籍内容
        /// </summary>
        /// <returns></returns>
        public static BookEntity GetCurrentBook()
        {
            return BookDAL.GetAllBook().First(x => x.BookId == new UserConfig().UserBookId);
        }

        #endregion

        #region public property

        /// <summary>
        /// 用户单词本
        /// </summary>
        public static List<WordEntity> WordBook
        {
            get
            {
                if (_wordbook == null)
                    InitUserWord();
                return _wordbook;
            }
            set { _wordbook = value; }
        }

        /// <summary>
        /// 是否从备份中恢复
        /// </summary>
        public static bool IsNeedReflesh { get; set; }

        #endregion

        #region private method

        /// <summary>
        /// 当前的书籍中，是否存在需要复习的熟词
        /// </summary>
        /// <returns></returns>
        public static List<WordEntity> GetCompletedWordToReviewWithoutQueue()
        {
            return new UserDataDAL().GetCompletedWordToReview().Where(x => !WordQueueManager.Contains(x)).ToList();
        }

        /// <summary>
        /// 单词本中是否还有未复习（达到了复习时间，不在队列中）的单词
        /// </summary>
        private static bool IsHaveWordInWordBook()
        {
            return GetReviewWordBookWithoutQueue().Count != 0;
        }

        /// <summary>
        /// 获得队列中没有的 待复习单词
        /// </summary>
        /// <returns></returns>
        private static List<WordEntity> GetReviewWordBookWithoutQueue()
        {
            return ReviewManager.GetReviewWordBook().Where(x => !WordQueueManager.Contains(x))
                .OrderBy(x => x.RememberLevel).ToList();
        }

        /// <summary>
        /// 异步保存
        /// </summary>
        /// <param name="wordEntity"></param>
        private static void Edit(WordEntity wordEntity)
        {
            //new Thread(() => new UserDataDAL().EditOrCreate(wordEntity.ToTable())).Start();
            new UserDataDAL().EditOrCreate(wordEntity.ToTable());
        }

        #endregion

    }
}
